package adminorg;

import java.io.Serializable;
import com.google.gdata.data.docs.DocumentListEntry;
import com.google.gdata.data.docs.DocumentListFeed;
import com.google.gdata.data.acl.AclEntry;
import com.google.gdata.data.acl.AclFeed;
import com.google.gdata.data.acl.AclRole;
import com.google.gdata.data.acl.AclScope;
import java.util.LinkedHashMap;
import java.util.HashSet;
import com.vaadin.data.Container.Filter;
import com.vaadin.data.util.filter.Compare.Equal;
import com.oros.db.*;
import com.oros.utils.*;

public class DocumentServe implements Serializable {

	private static final String APPLICATION_NAME = "ADMINORGSCHEMAVERSION1.0";
    public static final String ROLE_READER = "reader";
    public static final String ROLE_WRITER = "writer";
	private static final long serialVersionUID = -3442250710974829840L;
        private DatabaseHelper dbHelp;
        private int companyRef;
    public DocumentServe(DatabaseHelper dbHelp)
    {
         this.dbHelp = dbHelp;	
    }
    public DocumentList getDocumentList() throws Exception
    {
    	Integer company = dbHelp.getCompanyId();
    	if (company==null) return null;
    	DocumentList documentList=null;
    	if (company.intValue()!=companyRef)
    	{
    		documentList=null;
    		companyRef = company.intValue();
    	}
    	if (documentList==null)
    	{
    		documentList=new DocumentList(APPLICATION_NAME,DocumentList.DEFAULT_HOST);
    		try
    		{
    			String user = (String)dbHelp.getCompContainer().getContainerProperty(company, "email").getValue();
    			String pass = (String)dbHelp.getCompContainer().getContainerProperty(company, "password").getValue();
    			documentList.login(user.trim(), pass.trim());
    		}
    		catch(Exception e)
    		{
    			documentList=null;
    			throw e;
    		}
    	}
    	return documentList;
    }
    public DocumentList getUserDocumentList() throws Exception
    {
    	DocumentList documentList=null;
    	if (documentList==null)
    	{
    		documentList=new DocumentList(APPLICATION_NAME,DocumentList.DEFAULT_HOST);
    		try
    		{
    			String user = (String)dbHelp.getCurrentUserTrackItem().getItemProperty("email").getValue();
    			String pass = (String)dbHelp.getCurrentUserTrackItem().getItemProperty("auth").getValue();
    			if (pass==null || pass.length()==0) pass="orel1970";
    			documentList.login(user.trim(), pass.trim());
    		}
    		catch(Exception e)
    		{
    			documentList=null;
    			throw e;
    		}
    	}
    	return documentList;
    }    
    public LinkedHashMap<String,String> getUserOwnFileList() throws Exception
    {
    	LinkedHashMap<String,String> flist=new LinkedHashMap<String,String>();
    	DocumentList documentList = getUserDocumentList();
    	DocumentListFeed feed = documentList.getDocsListFeed("all");
    	for (DocumentListEntry entry : feed.getEntries()) 
    	{
    		String resourceId = entry.getResourceId();
    		String name = entry.getFilename();
    		System.out.println("Found info: "+resourceId+" -> "+name);
    		flist.put(resourceId, name);
    	}
    	return flist;
    }
    public String getNewlyCreatedDocument(String type,String title) throws Exception
    {
    	if (type==null) return "";
    	DocumentList documentList = getDocumentList();
    	if (type.equals("document") || type.equals("spreadsheet"))
    	{
    		//return "https://docs.google.com/document/d/1U9oRiLvwrSx5KevHsHvpWmHUsTFp6qkcih5N6eE9FoQ/edit";
    		DocumentListEntry doc = documentList.createNew(title, type);
    		String resourceId = doc.getResourceId();
    		int pos = resourceId.indexOf(':');
    		if (pos>=0) resourceId=resourceId.substring(pos+1).trim();
    		addRole(documentList,ROLE_WRITER,dbHelp.currentUser,resourceId);
    		return resourceId;
    	}
    	if (type.equals("folder"))
    	{
    		//return "https://docs.google.com/spreadsheet/ccc?key=0ArtW4im_WCzTdDZsbzFJZlRLSjJLb2tBYUlPS0ZSelE#gid=0";
    		DocumentListEntry doc = documentList.createNew(title, "folder");
    		return doc.getResourceId();
    	}
    	
    	return "";
    }
    public void removeDocument(String resourceId,boolean foreverAndEver) throws Exception
    {
    	DocumentList documentList=getDocumentList();
    	documentList.trashObject(resourceId, foreverAndEver);
    }
    private void addRole(DocumentList documentList,String role,String email,String resourceId) throws Exception
    {
    	AclRole aclRole = new AclRole(role);
        AclScope scope;
        if (email.indexOf('@')>=0) {
          scope = new AclScope(AclScope.Type.USER, email);
        } else {
          scope = new AclScope(AclScope.Type.DOMAIN, email);
        }
        documentList.addAclRole(aclRole, scope, resourceId);                	
    }
    private void changeRole(DocumentList documentList,String role,String email,String resourceId) throws Exception
    {
    	AclRole aclRole = new AclRole(role);
        AclScope scope;
        if (email.indexOf('@')>=0) {
          scope = new AclScope(AclScope.Type.USER, email);
        } else {
          scope = new AclScope(AclScope.Type.DOMAIN, email);
        }
        documentList.changeAclRole(aclRole, scope, resourceId);                	
    }
    private void removeRole(DocumentList documentList,String email,String resourceId) throws Exception
    {
    	String scope = email.indexOf('@')>=0?"user":"domain";
    	documentList.removeAclRole(scope, email, resourceId);
    }
    public void checkResourceRoles(DocumentList documentList,LinkedHashMap<String,String> emailRoleMap,String resourceId) throws Exception
    {
    	if (documentList==null) documentList = getDocumentList();
    	System.out.println("ResourceId:"+resourceId+" has "+emailRoleMap.size()+" roles");
    	for(String ks:emailRoleMap.keySet())
    	{
    		System.out.println(ks+"->"+emailRoleMap.get(ks));
    	}
        AclFeed feed = documentList.getAclFeed(resourceId);
        if (feed != null) {
          for (AclEntry entry : feed.getEntries()) {
        	  String email = entry.getScope().getValue();
        	  String role = entry.getRole().getValue();
        	  String mustRole =emailRoleMap.get(email);
        	  if (mustRole==null)
        	  {
        		  if (!role.equals("owner"))
        		  {
        			      System.out.println("role removing "+email+" from "+resourceId);
        		          removeRole(documentList,email,resourceId);
        		          
        		  }
        	  }
        	  else
        	  {
        		  System.out.println("Present roles: new-"+mustRole+" old-"+role+" email-"+email+" resourceId:"+resourceId);
        		  if (!mustRole.equals(role))
        		  {
        			  changeRole(documentList,mustRole,email,resourceId);
        		  }
        		  emailRoleMap.remove(email);
        	  }
          }
        }
        for(String email:emailRoleMap.keySet())
        {
        	String mustRole = emailRoleMap.get(email);
        	System.out.println("Introducing new roles: "+mustRole+" email:"+email+" resourceId:"+resourceId);
			addRole(documentList,mustRole,email,resourceId);
        }
    }
    private void checkDocumentRights(AEViewContainer container,DocumentList documentList) throws Exception
    {
        String resourceId=null;
        LinkedHashMap<String,String> emailRoleMap = new LinkedHashMap<String,String>();
        int n = container.size();
        int colLink = container.getColumnIndex("documents.link");
        int colEmail = container.getColumnIndex("compacc.email");
        int colRight = container.getColumnIndex("docrights.right");
        for(int i=0;i<n;i++)
        {
        	Object itemId = container.getIdByIndex(i);
        	AERawItem item =(AERawItem) container.getItem(itemId);
        	if (resourceId==null) resourceId=(String)item.getColumnValue(colLink);
        	String email = (String)item.getColumnValue(colEmail);
        	Integer right = (Integer)item.getColumnValue(colRight);
        	String role = right==null || right.intValue()==3?ROLE_READER:ROLE_WRITER;
        	String prevRole = emailRoleMap.get(email);
        	if (prevRole==null || (!prevRole.equals(role) && !prevRole.equals(ROLE_WRITER)))
        	{
        		emailRoleMap.put(email, role);
        	}
        }
        if (resourceId!=null) checkResourceRoles(documentList,emailRoleMap,resourceId);
    }

    private void notifyOfDocumentPostChange(Integer docId,DocumentList documentList) throws Exception
    {
    	if (documentList==null) documentList = getDocumentList();
    	AEViewContainer container = dbHelp.views.getWorkDocumentViewContainer();
    	container.cleanAndAddContainerFilter(new Equal("docrights.docid",docId));
    	checkDocumentRights(container,documentList);
    }
    private void notifyOfOrgschemaPostChange(Integer postId,DocumentList documentList) throws Exception
    {
    	if (documentList==null) documentList = getDocumentList();
    	AEViewContainer container = dbHelp.views.getWorkDocumentViewContainer();
    	HashSet<?> pst=container.getDistinctColumnValuesUnfiltered("docrights.docid",new Filter[]
    			{new Equal("docrights.post",postId)});
    	for(Object post:pst)
    	{
    		notifyOfDocumentPostChange((Integer)post,documentList);
    	}
    }
    public void notifyOfOrgschemaPostChange(Object postId) throws Exception
    {
    	Integer iPostId;
    	if (postId instanceof Integer) iPostId=(Integer)postId;
    	else iPostId=new Integer(Integer.parseInt(postId.toString()));
    	notifyOfOrgschemaPostChange(iPostId,null);
    }
    public void notifyOfDocumentPostRightChange(Object docId) throws Exception
    {
    	Integer iDocId;
    	if (docId instanceof Integer) iDocId=(Integer)docId;
    	else iDocId=new Integer(Integer.parseInt(docId.toString()));
    	notifyOfDocumentPostChange(iDocId,null);
    }
    public void notifyOfCompAccChange(Object aCompAccId) throws Exception
    {
    	Integer compAccId;
    	if (aCompAccId instanceof Integer) compAccId=(Integer)aCompAccId;
    	else compAccId=new Integer(Integer.parseInt(aCompAccId.toString()));
    	DocumentList documentList = getDocumentList();
    	HashSet<?> pst=dbHelp.getOrgschemaReadContainer().getDistinctColumnValuesUnfiltered("id",new Filter[]
    			{new Equal("accid",compAccId)});
    	for(Object post:pst)
    	{
    		notifyOfOrgschemaPostChange((Integer)post,documentList);
    	}
    }
    public static String getDocumentLink(String resourceId,String type,String title,boolean isEdit)
    {
    	
    	if (type.equals("document"))
    	{
    		return "<a href=\"https://docs.google.com/document/d/"+resourceId+"/"+(isEdit?"edit":"view")+"\" target=\"_blank\">"+title+"</a>";
    	}
    	if (type.equals("spreadsheet"))
    	{
    		return "<a href=\"https://docs.google.com/spreadsheet/ccc?key="+resourceId+"#gid=0\" target=\"_blank\">"+title+"</a>";
    	}
    	return resourceId;
    }
}
